﻿using System;
using System.Windows;
using System.Windows.Controls;
using ChessKit.Common;

namespace ChessKit.Ui
{
  public class ResourcePiece : ContentControl
  {
    #region ' PieceType '

    public static readonly DependencyProperty PieceTypeProperty =
      DependencyProperty.Register("PieceType", typeof(PieceType),
      typeof(ResourcePiece), new PropertyMetadata(default(PieceType), OnPieceTypeChanged));

    private static void OnPieceTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      ((ResourcePiece)d).UpdateContent();
    }

    public PieceType PieceType
    {
      get { return (PieceType) GetValue(PieceTypeProperty); }
      set { SetValue(PieceTypeProperty, value); }
    }

    #endregion

    #region ' PieceColor '

    public static readonly DependencyProperty PieceColorProperty =
      DependencyProperty.Register("PieceColor", typeof(PieceColor),
      typeof(ResourcePiece), new PropertyMetadata(default(PieceColor), OnPieceColorChanged));

    private static void OnPieceColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      ((ResourcePiece)d).UpdateContent();

    }

    public PieceColor PieceColor
    {
      get { return (PieceColor) GetValue(PieceColorProperty); }
      set { SetValue(PieceColorProperty, value); }
    }

    #endregion

    #region ' ResourceUri '

    public static readonly DependencyProperty ResourceUriProperty =
      DependencyProperty.Register("ResourceUri", typeof (Uri), typeof (ResourcePiece),
      new PropertyMetadata(default(Uri), OnResourceUriChanged));

    private static void OnResourceUriChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
      ((ResourcePiece) dependencyObject).UpdateContent();
    }

    public Uri ResourceUri
    {
      get { return (Uri)GetValue(ResourceUriProperty); }
      set { SetValue(ResourceUriProperty, value); }
    }

    #endregion

    #region ' Piece '

    public static readonly DependencyProperty PieceProperty =
      DependencyProperty.Register("Piece", typeof (IPiece),
      typeof (ResourcePiece), new PropertyMetadata(default(IPiece), OnPieceChanged));

    private static void OnPieceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      ((ResourcePiece)d).UpdateContent();
    }

    public IPiece Piece
    {
      get { return (IPiece)GetValue(PieceProperty); }
      set { SetValue(PieceProperty, value); }
    }

    #endregion

    static ResourcePiece()
    {
      ResourcePool = new KeyedObjectsPool<Uri, FrameworkElement>(uri =>
          {
            try
            {
              return Application.LoadComponent(uri) as FrameworkElement;
            }
            catch (Exception exception)
            {
              Console.WriteLine(exception);
              return null;
            }
          }); 

    }

    private Uri _currentReourceUri;

    private void UpdateContent()
    {
      var uri = GetUri();
      
      if (_currentReourceUri == uri) return;

      if (Content != null)
        ResourcePool.Release(_currentReourceUri, (FrameworkElement) Content);

      _currentReourceUri = uri;

      Content = _currentReourceUri == null 
        ? null : ResourcePool.Aquire(_currentReourceUri);
    }

    private Uri GetUri()
    {
      if (ResourceUri == null) return null;

      string pieceName;
      if (Piece != null)
      {
        pieceName = Piece.Color + " " + Piece.Type;
      }
      else
      {
        if (PieceType == 0) return null;
        pieceName = PieceColor + " " + PieceType;
      }

      return new Uri(ResourceUri + "/" + pieceName + ".xaml", UriKind.Relative);
    }

    private static readonly KeyedObjectsPool<Uri, FrameworkElement> ResourcePool;
  }
}
